<template>
	<view class="">
		<!-- #ifndef H5 -->
		<video id="myVideo" style="width:100%;height:460rpx" :picture-in-picture-mode="[]" :controls="true"
			:show-background-playback-button="false" :show-center-play-btn="false" :title="params.name"
			:initial-time="initialTime" :src="params.url" :poster="params.poster" @play="onPlay" @pause="onPause"
			@ended="onEnded" @timeupdate="onTimeupdate" @fullscreenchange="onFullscreenchange" @loadstart="loadstart"
			@error="videoErrorCallback" @loadedmetadata="onLoadedMetaData" :custom-cache="false"></video>

		<!-- #endif -->
		<!-- #ifdef H5 -->
		<div id="myVideo" ref="myVideo"></div>
		<debug v-if="isDebug" :params="params" :studentInfo="studentInfo" :state="state" :beat="beat"></debug>
		<!-- #endif -->
	</view>
</template>

<script>
	import vapi from '@/api/index.js';
	import debug from '@/components/debug';
	import config from '@/config';
	// #ifdef H5
	import Player from 'xgplayer';
	// #endif
	var graceJs = require('@/utils/grace.js');
	export default {
		name: 'kvideo',
		props: ['query'],
		components: {
			debug
		},
		data() {
			return {
				hidePlayBtn: false,
				rqTime: 0, // 请求时间
				isFullscreen: false,
				beyond: 1, // 超出 1S 进度拉回
				isLogin: config.isLogin(),
				isDebug: config.isDebug,
				videoContext: null,
				isReady: true,
				freeTime: 360, // 试看秒数 6分钟
				pant: 110, // 心跳秒数
				learningToken: '', // 学习token
				isClick: true,
				playStatus: '',
				learnSum: 0, // 累计提交
				learnTime: 0, // 阶段学习时长
				pTime: 0, // 播放器的播放时长，
				cTime: 0, // 自己计算的播放时长，
				width: 0,
				height: 0,
				totalLearnNum: 0,
				state: {
					learnStatus: '',
					playStatus: '',
					learningToken: '',
					learnLength: '',
					diff: '',
					viewingLength: '',
					learnSum: '',
					learnTime: '',
					error: ''
				},
				learnStatus: 0, // 0 未学 1 未学完 2 学完 整个课程的状态
				studentInfo: {
					chapterId: '', // 章ID
					classesId: '', // 班级ID
					courseId: '', // 资源ID
					demandLength: '', // 需求长度
					lastTime: null, // 最后一次学习时间
					learnLength: 0, // 已学长度
					learnStatus: 0, // 1 在学 2 学习完成
					nodeId: '', // 节ID
					studentId: '' // 用户id
				},
				params: {},
				done: false,
				event: [],
				timer: null,
				timer_: null,
				isRedis: false,
				storageKey: 'state',
				isStart: false,
				initialTime: 0,
				ctu: true,
				uptime: 0,
				beat: {},
				errorStatus: null,
				errorText: '',
				ycNum: 0,
				oldPlayStatus: '',
				drag: true,
			};
		},

		watch: {
			event: {
				handler: function(n, o) {
					if (n.length > 0) {
						this.axStatus();
					}
				},
				immediate: true,
				deep: true
			}
		},

		computed: {
			// 视频学习状态 1试看 2学习(开始/继续) 3回看
			// learnStatus 0 未学 1 未学完 2 学完 整个课程的状态 courseStatus
			// studentInfo learnLength (已学长度) learnStatus 1(已购买未学完) 2(已购买已学完)
			learnStaus() {
				if (!this.isLogin || !this.learnStatus || !this.params.classesId || this.params.courseStatus == 2) {
					return 1;
				} else if (this.studentInfo.learnStatus == 1) {
					return 2;
				} else if (this.studentInfo.learnStatus == 2) {
					return 3;
				}
			}
		},

		methods: {
			// 播放
			async playerAudio(l, s, p) {
				// #ifdef H5
				if (p.demandLength == p.learnLength) {
					this.drag = false;
				} else {
					this.drag = true;
				}
				// #endif
				if (this.videoContext) {
					// #ifdef H5
					this.videoContext.config.disableProgress = this.drag;
					// #endif
					this.stateInit(l, s, p, true);
				} else {
					await this.$nextTick();
					// #ifdef H5
					console.log(this.drag)
					this.videoContext = new Player({
						id: 'myVideo',
						url: p.url,
						poster: p.poster,
						// 'time': params.demandLength * 1,
						'x5-video-player-type': 'h5', //微信同层播放
						'x5-video-player-fullscreen': false,
						playsinline: false,
						'webkit-playsinlin': false,
						'picture-in-picture-mode': [],
						'show-background-playback-button': false,
						// autoplay: params.autoplay | false,
						fluid: true,
						defaultPlaybackRate: 1,
						lang: 'zh-cn',
						closeVideoClick: true,
						closeVideoTouch: true,
						// lastPlayTime: params.learnLength * 1,
						lastPlayTimeHideDelay: 5, //提示文字展示时长（单位：秒）
						keyShortcut: 'off',
						//使移动端支持双击暂停/播放
						enableVideoDbltouch: true,
						height: 370,
						miniplayer: false,
						pip: false,
						//支持进度条只能拖动到已播过部分（播放器被接管或劫持时无效，比如iOS或安卓部分环境下）
						// allowSeekPlayed: _this.isLogin && params.classesId
						disableProgress: this.drag //禁止进度条拖动交互
					});

					this.videoContext.on('play', e => {
						if (!e) return;
						this.checkPlayStatus('play');
						this.errorStatus = null;
					});

					this.videoContext.on('pause', e => {
						if (!e) return;
						this.checkPlayStatus('pause', e.currentTime);
					});

					this.videoContext.on('ended', e => {
						if (!e) return;
						this.checkPlayStatus('ended', e.currentTime);
					});

					this.videoContext.on('playbackrateChange', e => {
						if (!e) return;
						this.videoContext.reload();
						that.go();
					});

					this.videoContext.on('waiting', e => {
						this.isReady = false;
						this.invalidFn();
					});

					this.videoContext.on('canplay', e => {
						this.isReady = true;
						if (this.learnStaus == 2 && !this.isStart) {
							this.videoContext.currentTime = this.pTime * 1;
							this.isStart = true;
						}
					});

					this.videoContext.on('error', e => {
						if (!e) return;
						this.checkPlayStatus('error', e);
					});

					// 监听进入全屏状态
					this.videoContext.on('requestFullscreen', e => {
						this.isFullscreen = true;
					});

					// 监听退出全屏状态
					this.videoContext.on('exitFullscreen', e => {
						this.isFullscreen = true;
					});

					this.videoContext.on('timeupdate', e => {
						if (!e.currentTime) return;
						this.checkPlayStatus('timeupdate', e.currentTime);
					});
					// #endif

					// #ifndef H5
					this.videoContext = uni.createVideoContext('myVideo', this);
					// #endif
					this.stateInit(l, s, p, false);
				}
			},

			//播放
			onPlay(e) {
				if (!e) return;
				this.errorStatus = null;
				this.checkPlayStatus('play');
			},

			// 播放中
			onTimeupdate(e, v) {
				this.isReady = true;
				if (!e) return;
				let n = new Date().getTime();
				if (this.ctu) {
					this.checkPlayStatus('timeupdate', e.detail.currentTime);
					this.uptime = n;
					return;
				}
				if (n - this.uptime >= 300) {
					this.checkPlayStatus('timeupdate', e.detail.currentTime);
					this.uptime = n;
				}
			},

			// 播放结束
			onEnded(e) {
				if (!e) return;
				this.checkPlayStatus('ended', e.detail.currentTime);
			},

			// 播放暂停
			onPause(e) {
				if (!e) return;
				this.checkPlayStatus('pause', e.detail.currentTime);
			},

			// 视频缓冲
			loadstart() {
				this.isReady = false;
				this.invalidFn();
			},

			// 错误
			videoErrorCallback(e) {
				if (!e) return;
				this.checkPlayStatus('error', e);
			},

			// 全屏
			onFullscreenchange(e) {
				if (!e) return;
			},

			// 视频加载完成
			onLoadedMetaData(e) {
				console.log('加载完成', this.learnSum);
			},

			invalidFn() {
				let v = (this.getTime() - this.rqTime) / 1000;
				if (v > 60 && this.isRedis) {
					this.handledBefor(this.learnTime, false);
					// #ifdef H5
					let {
						readyState,
						networkState
					} = this.videoContext;
					if (this.learnStaus != 1) {
						uni.showLoading({
							title: '加载中',
							mask: true
						});
						setTimeout(function() {
							uni.hideLoading();
						}, 1000);
					}
					console.log('网络状态：', readyState, networkState);
					// #endif
				}
			},

			// 播放状态初始化
			async stateInit(l, s, par, t) {
				let {
					videoContext,
					freeTime
				} = this;
				if (!videoContext) return;
				this.learnStatus = l;
				this.studentInfo = JSON.parse(JSON.stringify(s));
				let temp = JSON.parse(JSON.stringify(par));
				if (escape(temp.url).indexOf('%u') >= 0) {
					temp.url = encodeURI(temp.url);
				}
				this.params = temp;
				// this.isReady = false; // 视频加载中
				this.updateState = true;
				this.learnSum = 0;
				this.isStart = false;

				// #ifndef H5
				if (t) {
					this.ctu = false;
					this.$nextTick(() => {
						this.pTime = this.params.learnLength * 1;
						this.videoContext.play();
						if (this.pTime != 0) {
							videoContext.seek(this.params.learnLength * 1);
						}
						this.ctu = true;
					})
					setTimeout(() => {

					}, 200);
				} else {
					this.$nextTick(() => {
						this.pTime = this.params.learnLength * 1;
						this.initialTime = this.params.learnLength * 1;
						this.videoContext.play();
					})

					setTimeout(() => {

					}, 200);
				}
				// #endif

				// #ifdef H5
				this.pTime = this.params.learnLength * 1;
				this.videoContext.src = this.params.url;
				this.videoContext.poster = this.params.poster;
				this.videoContext.start(this.params.url);
				this.videoContext.play();
				// #endif
			},

			// 播放状态处理
			checkPlayStatus(type, e) {
				let {
					videoContext,
					pant,
					freeTime,
					pTime,
					beyond,
					isFullscreen,
					learnSum,
					query,
					ctu
				} = this;
				let that = this;
				this.playStatus = type;
				this.setState();
				// uni.hideLoading();
				if (type == 'error' || !ctu) {
					return;
				}
				if (type == 'play') {
					this.hidePlayBtn = false;
					this.done = false;
					if (this.learnStaus != 2) return;
					this.cTime = this.getTime();
					this.handledBefor(0, false);
					return;
				}

				if (type == 'timeupdate') {
					this.hidePlayBtn = false;
					if (this.learnStaus == 1) {
						if (e >= freeTime && !this.done) {
							this.freePlayOver();
						}
					}

					if (this.learnStaus == 2) {
						let s1 = this.params.learnLength * 1 + this.learnSum;
						if (s1 > e) return;
						let a = e - pTime;
						let b = (this.getTime() - this.cTime) / 1000;
						a = a < 0 ? 0 : a;
						b = b < 0 ? 0 : b;
						if (a - b > beyond) {
							console.log('timeupdate', a, b);
							this.setSeek('sum');
							uni.showModal({
								title: '提示',
								content: '请耐心学习',
								confirmText: '知道了',
								showCancel: false
							});
							this.errorText = `${this.errorText}  ${e}-${pTime}进度超出1秒`;
							this.setState();
							return;
						} else {
							this.learnTime += e - pTime;
							// console.log('播放时长：' + this.learnTime)
							this.cTime = this.getTime();
							this.pTime = e;
						}
						let length = Math.ceil(this.learnTime);
						let sum = s1 + length;
						if (length > 0 && length % pant == 0 && sum < this.params.demandLength) {
							console.log("播放时长", length, "总时长", sum);
							this.learnTime = 0;
							this.handledBefor(length, false);
						}
					}
				}

				if (type == 'pause') {
					this.hidePlayBtn = true;
					graceJs.delay(200, () => {
						if (this.learnStaus == 2 && this.playStatus == 'pause') {
							// 计算当前已学时长并提交
							let length = Math.ceil(this.learnTime);
							if (length > 1) {
								this.handledBefor(length, false);
							} else {
								this.setSeek(this.pTime, false);
								this.learnTime = 0;
								this.setState();
							}
						}
					});
				}

				if (type == 'ended') {
					this.hidePlayBtn = true;
					if (this.learnStaus == 1) {
						this.freePlayOver();
						return;
					}

					if (this.learnStaus == 2) {
						let max = this.params.demandLength * 1;
						let a = max - pTime;
						let b = (this.getTime() - this.cTime) / 1000;
						a = a < 0 ? 0 : a;
						b = b < 0 ? 0 : b;
						if (a - b < 20) {
							let length = Math.ceil(this.learnTime);
							if (length > 0) {
								this.handledBefor(length, true);
							} else {
								this.changeNextNode();
							}
						} else {
							this.setSeek('sum');
							this.errorText = `${this.errorText}  ${type}学习误差${a - b}秒${max}-${pTime}-${a}`;
							uni.showModal({
								title: '提示',
								content: '网络延迟导致结束异常，请重新播放！',
								showCancel: false,
								confirmText: '确认'
								// success: function(res) {
								// 	that.go();
								// }
							});
							this.setState();
						}
					}

					if (this.learnStaus == 3) {
						this.changeNextNode();
					}
				}
			},

			handledBefor(len, next) {
				console.log("心跳数据", this.playStatus, len, next, this.isReady, this.ycNum);
				if (this.isRedis) {
					this.ycNum = 0;
					this.event.push({
						len,
						next,
						type: this.playStatus
					});
				} else {
					// if (this.oldPlayStatus != this.playStatus || !this.ycNum) {
					// 	uni.showToast({
					// 		title: '您的网络延迟较高',
					// 		icon: 'none',
					// 		mask: false,
					// 		duration: 1500
					// 	});
					// }
					this.ycNum++;

					console.log(this.oldPlayStatus, this.playStatus)
					if (this.oldPlayStatus == this.playStatus && this.playStatus == 'timeupdate') {
						let t = this.getTime()
						let b = (t - this.cTime) / 1000;
						console.log(`堵塞：', ${b}, ${t}, ${this.cTime}`)
						if (b < 6) return;
					}
					this.oldPlayStatus = this.playStatus;
					let l = this.maxNum(len, 5);
					this.learnTime -= l;
					console.log(`堵塞2：', ${this.ycNum}, ${l}, ${len-l}`)
					// if (this.ycNum >= 2 || !l) {
					if (!l) {
						this.setSeek(len - l);
						this.oldPlayStatus = '';
					}
					// else {
					// 	this.setSeek(len - l, false);
					// 	uni.showToast({
					// 		title: '网络延迟导致进度记录失败,请重新播放！',
					// 		icon: 'none',
					// 		duration: 2000
					// 	});
					// }
				}
			},

			maxNum(len, v) {
				if (len > v) {
					return v;
				} else {
					if (v - 1 == 0) {
						return 0;
					} else {
						this.maxNum(len, v - 1);
					}
				}
			},

			async setSeek(v, t = true) {
				await this.$nextTick();
				if (v == 'sum') {
					v = this.params.learnLength * 1 + this.learnSum;
					this.learnTime = 0;
				} else if (v > this.params.demandLength) {
					v = this.params.demandLength;
				} else if (v < 0 || isNaN(v)) {
					v = 0;
				}
				console.log('setseek', this.playStatus, v, t);
				if (v) {
					// #ifdef H5
					this.videoContext.currentTime = v;
					// #endif
					// #ifndef H5
					this.videoContext.seek(v);
					// #endif
				}
				if (!t) {
					this.videoContext.pause();
				}
			},

			setState() {
				let max = this.params.demandLength;
				let sum = this.params.learnLength * 1 + this.learnSum + this.learnTime;
				let cv = max - sum;
				this.state = Object.assign({}, this.state, {
					learnStatus: this.learnStatus,
					playStatus: this.playStatus,
					learningToken: this.learningToken,
					diff: cv,
					error: this.errorText,
					learnLength: this.params.learnLength,
					learnSum: this.learnSum,
					learnTime: this.learnTime,
					pTime: this.pTime
				});
			},

			go() {
				uni.redirectTo({
					url: `/pages/courseMarket/detail/index${this.query}&t=${new Date().getTime()}`
				});
			},

			// 退出全屏
			exitFullscreen() {
				if (this.videoContext.fullscreen) {
					this.videoContext.exitFullscreen(this.videoContext.root);
					this.videoContext.exitFullscreen();
				}
			},

			// 试看结束
			freePlayOver() {
				var szhy = config.storage(['user_info', 'szhy']);
				this.exitFullscreen();
				this.done = true;
				this.setSeek(this.freeTime, false);
				for (let i = 1; i < 100; i++) {
					clearInterval(i);
				}
				var that = this;
				var courseStatus = this.params.courseStatus;
				var msg = '试看结束，如需继续观看，请购买课程，是否加入购物车？';
				if (szhy == '01' || szhy == '11') {
					msg = '试看结束，如需继续观看，请前往课程超市进行购买，是否立即前往？';
				} else {
					if (courseStatus == 0) {
						msg = '试看结束，如需继续观看，请购买课程，课程已在购物车中，是否进入购物车去结算？';
					} else if (courseStatus == 2) {
						msg = '试看结束，如需继续观看，请购买课程，课程有存在支付中订单，是否继续支付？';
					}
				}
				that.setState();
				uni.showModal({
					title: '提示',
					content: msg,
					success: res => {
						if (res.confirm) {
							if (szhy == '01' || szhy == '11') {
								that.$uni.navigate(`/pages/courseMarket/index`, 'switchTab');
							} else {
								if (courseStatus == 0) {
									that.$uni.navigate(`/pages/shoppingCart/index`, 'switchTab');
								} else if (courseStatus == 2) {
									that.$uni.navigate(`/pagesA/order/index`, 'redirectTo');
								} else {
									that.$emit('handleShoppingCart');
								}
							}
						} else if (res.cancel) {}
					}
				});
			},

			// 心跳提交
			heartbeatApi(len, next = false) {
				console.log("心跳提交");
				return new Promise(resolve => {
					this.learningToken = len == 0 ? '' : this.learningToken;
					len = this.learningToken == '' ? 0 : len;
					this.$api.heartbeat({
							chapterId: this.params.chapterId,
							classesId: this.params.classesId,
							courseId: this.params.courseId,
							learningToken: this.learningToken,
							nodeId: this.params.nodeId,
							sourceType: 2,
							studentId: config.storage(['user_info', 'id']),
							viewingLength: len
						},
						e => {
							this.beat = e;
							this.state.viewingLength = len;
							this.setState();
							this.errorStatus = e.status;
							if (e.status == '0') {
								this.learnSum += len;
								this.learningToken = e.data;
								// this.queryNewestStudent(next, resolve);

								let v = Math.ceil((this.pTime / this.params.demandLength) * 100);
								v = v > 100 ? 100 : v;
								this.$emit('updateProgress', v);
								if (next) this.changeNextNode();
							} else {
								if (e.status == 1 || e.status == 2) {
									uni.showModal({
										title: '提示',
										content: '网络延迟导致进度记录失败，请重新播放！',
										showCancel: false,
										confirmText: '确认',
										success: function(res) {
											if (res.confirm) {
												uni.redirectTo({
													url: `/pagesC/myStudy/course`
												});
												console.log('用户点击确定');
											} else if (res.cancel) {
												console.log('用户点击取消');
											}
										}
									});
								}
								if (e.data) {
									// uni.showModal({
									// 	title: '提示',
									// 	content: e.data,
									// 	showCancel: false
									// });
								}
								this.errorText =
									`${this.errorText}  状态:${e.status}时长:${len}回退:${this.learnSum}总时长${this.params.demandLength}`;
								this.setSeek('sum');
							}
							this.resetEvent();
						},
						(e) => {
							console.log('接口超时：', e)
							this.resetEvent();
							this.setSeek('sum');
							if (e == 'request:fail timeout') {
								uni.showModal({
									title: '提示',
									content: `您的网络环境无法正常提交学时，请切换网络。`,
									showCancel: false,
									confirmText: '确认',
									success: function(res) {
										if (res.confirm) {
											uni.redirectTo({
												url: `/pagesC/myStudy/course`
											});
											console.log('用户点击确定');
										} else if (res.cancel) {
											console.log('用户点击取消');
										}
									}
								});
							}
						}
					);
				});
			},

			resetEvent() {
				if (this.playStatus != 'timeupdate') {
					this.learnTime = 0;
				}
				this.isRedis = true;
				this.rqTime = this.getTime();
			},

			pause(t) {
				let {
					learnStatus,
					studentInfo,
					params,
					learnTime,
					pTime,
					storageKey
				} = this;
				if (t) {
					if (this.videoContext) {
						this.videoContext.pause();
						this.$router.back();
					}
				} else {
					this.$router.back();
				}
			},

			// 请求更新当前节
			queryNewestStudent: function(next, resolve) {
				this.$emit('queryNewestStudent', this.params, this.params, next, resolve);
			},

			// 请求播放下一节
			changeNextNode: function() {
				this.$emit('changeNextNode', this.params.chapterId, this.params.nodeId);
			},

			getTime() {
				return new Date().getTime();
			},

			axStatus() {
				let v = this.getTime() - this.rqTime;
				if (!this.event[0]) return;
				if (v > 1000 && this.isRedis) {
					this.isRedis = false;
					let e;
					if (this.event.length > 0) {
						this.event.forEach((item, index) => { //js遍历数组
							e = item;
						});
					} else {
						e = this.event.splice(0, 1)[0];
					}
					if (e.type == 'ended') {
						e.len = e.len + 2
					}
					this.heartbeatApi(Math.ceil(e.len), e.next);
				} else {
					console.log('排队事件:', this.event[0])
				}
			}
		},

		destroyed() {
			// #ifdef H5
			this.videoContext?.destroy();
			// #endif
			// #ifndef H5
			this.videoContext?.exitBackgroundPlayback()
			// #endif
		}
	};
</script>

<style scoped>
	.k-video {
		/* width: 750rpx;
		height: 230rpx;
		display: block;
		top: 0;
		left: 0;
		z-index: 900; */
	}

	.uni-video-cover {
		z-index: 901 !important;
	}

	.hideMe {
		display: none !important;
	}
</style>